local Util					= require("common.Util")
local SkillDefine 			= require("skill.Define")
local Obj		  			=  require("core.Obj")
local CoolDown		   		= require("skill.CoolDown")
local Buffer        = require("buffer.Buffer")
local ExcelMonster  = require("excel.Monster")
local RoleCombatMode = require("role.RoleCombatMode")
local RoleFFI = require("role.RoleFFI")
local ERR_SKILL_COOLDOWN	= SkillDefine.ERR_SKILL_COOLDOWN
local OBJ_SKILL_TARGET_TYPE_HUMAN			= 1	-- ObjSkill 只攻击人
local OBJ_SKILL_TARGET_TYPE_MONSTER 		= 2	-- ObjSkill 只怪物
local OBJ_SKILL_TARGET_TYPE_HUMAN_MONSTER	= 3	-- ObjSkill 只攻击人/怪物

local COMBAT_MODE_PEACE = 0 -- 和平模式 所有人都不攻击
local COMBAT_MODE_PVP = 1   -- 全体模式，所有人都能攻击
local COMBAT_MODE_TEAM = 2   -- 组队模式 , 攻击队外的人
local COMBAT_MODE_FAMILY = 3  -- 军团模式，  攻击军团外的人
local COMBAT_MODE_CAMPS = 4 --  阵营模式，不能攻击同一阵营的人
local COMBAT_MODE_WILD = 5    -- 野外模式，

local HUMAN_STATUS_HIDE						= 11-- 隐身

local ACTTACK_TYPE_SELF 					= SkillDefine.ACTTACK_TYPE_SELF

local random								= math.random


function isInWhiteMonsterList()--obj, target)
  return  
end

function canUseSkill(obj, skillID)--, target)
	local result = CoolDown.canUse(obj, skillID)
	if not result then return ERR_SKILL_COOLDOWN end -- 技能冷却中...
	return true
end

function canAddSkill()--obj, skillID, target)
	return true
end

-- ***************** 条件 ***********************
local data = {}

-- 判断目标是否可攻击
function canAttack(target)
	return (target.obj_type == Obj.TYPE_MONSTER or target.obj_type == Obj.TYPE_HUMAN or target.obj_type == Obj.TYPE_PET) and Obj.getHp(target)>0 or target.obj_type == Obj.TYPE_TRAP
end

-- 施法距离	(非自身时，判断距离)	radius = obj.radius + target.radius
function canAttackLen(utilityConfig, x, y, tx, ty, radius)
	if utilityConfig.acttackType ~= ACTTACK_TYPE_SELF and Util.dist(x,y,tx,ty) > utilityConfig.mouseToSelf + radius + 100 then
		return
	end
	return true
end 

-- 判断释放的前提条件
function prerequisites(obj, target, unit, utilityConfig)
	if not utilityConfig then return end
	
	data.obj			= obj
	data.target			= target
	data.unit			= unit
	data.utilityConfig	= utilityConfig
	
	-- 前提条件(判断自身)
	for _,conditionValue in ipairs(utilityConfig.prerequisites) do
		local conditionCallBack = _ENV[conditionValue[1]]
		if not conditionCallBack(data,obj,conditionValue[2],conditionValue[3],conditionValue[4]) then
			return
		end
	end
	return true
end

function friendAndFoeConditions(obj, target, friendFoeType)
	local callBack = friendFoeFuncs[friendFoeType]
	if callBack and not callBack(obj,target) then
		return
	end
	
	return true
end


function special(obj,target,unit)
  local utilityConfig = unit.utilityConfig
  if not canAttack(target) or (unit.sceneID ~= target.scene_id and utilityConfig.acttackCenter ~= ACTTACK_TYPE_SELF) then
    return 
  end
  if target.obj_type == Obj.TYPE_TRAP and obj ~= target then --trap 只能被自己释放kill技能
    return 
  end
  if target.hide and obj~=target then 
    return
  end
  
  if target.obj_type == Obj.TYPE_MONSTER and obj ~= target and target.can_hit==0  then
    return
  end
  
  
  if not friendAndFoeConditions(obj,target,utilityConfig.friendAndFoeConditions) then
    return
  end
  
  data.obj      = obj
  data.target     = target
  data.unit     = unit
  data.utilityConfig  = utilityConfig
  
  for _,specialCondition in ipairs(utilityConfig.specialConditions) do

    local conditionCallBack = _ENV[specialCondition[1]]
    if not conditionCallBack(data,target,specialCondition[2],specialCondition[3],specialCondition[4]) then
      return
    end

  end
  return true
end

-- ***************** 敌友条件 ***********************
-- 1：自己
function isSelf(obj,target)
	return obj == target
end


-- 2：敌人，在当前攻击模式下可攻击的单位。
function isEnemy(obj, target)
	obj		= Obj.getOwner(obj) or obj
	target	= Obj.getOwner(target) or target
	
	if obj == target then return end --攻击目标是自己
	local objType	 = obj.obj_type
	local targetType = target.obj_type
	
	if objType == Obj.TYPE_HUMAN then
		if targetType == Obj.TYPE_HUMAN then
			return human_VS_human(obj, target)
		elseif targetType == Obj.TYPE_MONSTER then
			return human_VS_monster(obj, target)
		end
		
	elseif objType == Obj.TYPE_MONSTER then
		if targetType == Obj.TYPE_HUMAN then
			return human_VS_monster(target, obj)
		else
			return obj.camps ~= target.camps
		end		
	elseif objType == Obj.TYPE_MAGIC then
		return obj.camps ~= target.camps
		
	elseif objType == Obj.TYPE_SKILL then
		if targetType == Obj.TYPE_HUMAN then
			local objSkillAtkType = obj.target_type
			return objSkillAtkType == OBJ_SKILL_TARGET_TYPE_HUMAN or objSkillAtkType == OBJ_SKILL_TARGET_TYPE_HUMAN_MONSTER
		elseif targetType == Obj.TYPE_MONSTER then
			local objSkillAtkType = obj.target_type
			return objSkillAtkType == OBJ_SKILL_TARGET_TYPE_MONSTER or objSkillAtkType == OBJ_SKILL_TARGET_TYPE_HUMAN_MONSTER
		end
	end
	
end

-- 3：敌方怪物，当前模式下可攻击的非玩家角色。
function isEnemyMonster(obj,target)
	return target.obj_type == Obj.TYPE_MONSTER and isEnemy(obj,target)
end

-- 4：敌方玩家，当前模式下可攻击的玩家角色。
function isEnemyHuman(obj,target)
	return target.obj_type == Obj.TYPE_HUMAN and isEnemy(obj,target)
end

-- 5：队友，同一队伍下的玩家以及玩家宠物。
function isTeam(obj, target)
	-- 取owener 
	obj		= Obj.getOwner(obj)		or obj
	target  = Obj.getOwner(target)  or target
	
	if obj == target then return true end
	
	if obj.obj_type ~= Obj.TYPE_HUMAN or target.obj_type ~= Obj.TYPE_HUMAN then 
		return 
	end
  
	if obj.db.teamUuidLen == 0 or target.db.teamUuidLen == 0 then
	  return
	end
	
	for i = 0, obj.db.teamUuidLen - 1 do
	   if RoleFFI.ffi_string(obj.db.teamUuid[i].uuid) == target._id then
	       return true
	   end
	end
end

-- 6：队友玩家，同一队伍下的玩家角色。
function isTeamHuman(obj,target)
	return target.obj_type == Obj.TYPE_HUMAN and isTeam(obj,target) 
end

-- 7：队友怪物，同一队伍下的非玩家角色。
function isTeamMonster(obj,target)
	return target.obj_type == Obj.TYPE_MONSTER and isTeam(obj,target)
end

-- 8：队友宠物，同一队伍下的非玩家角色。
function isTeamPet(obj,target)
	return target.obj_type == Obj.TYPE_PET and isTeam(obj,target)
end

-- 9：非敌方单位，当前模式下不可攻击的单位。
function isNotEnemy(obj,target)
	return not isEnemy(obj, target)
end

-- 10：友方（阵营）
function isFriend(obj,target)
	if isEnemy(obj,target) then	return 	end
	if isTeam(obj,target) then return true end
	if target.obj_type == Obj.TYPE_MONSTER and target.camps == Obj.CAMPS_GOOD then 
		return true
	end
	return true
end

-- 11：友方玩家与玩家宠物（阵营）(不包括怪物)
function isFriendPlayerAndPet(obj,target)
	return target.obj_type ~= Obj.TYPE_MONSTER and isFriend(obj,target)
end

-- 12: 主人
function isOwner(obj, target)
  local owner = Obj.getOwner(obj)
  return owner == target
end
-- 13: 自己或主人
function isOwnerOrSelf(obj, target)
  local owner = Obj.getOwner(obj)
  return (obj.obj_type ~= Obj.TYPE_TRAP and obj == target) or owner == target 
end


friendFoeFuncs = {isSelf,isEnemy,isEnemyMonster,isEnemyHuman,isTeam,isTeamHuman,isTeamMonster,isTeamPet,isNotEnemy,isFriend,isFriendPlayerAndPet,isOwner,isOwnerOrSelf}


-- *************** CombatMode 敌友关系(返回true为敌人)**********************

function human_VS_human(obj, target)
	local combatMode		= RoleCombatMode.getCombatMode(obj)
	if combatMode == COMBAT_MODE_PEACE then
		return	false
  elseif combatMode == COMBAT_MODE_PVP then
    return true
	elseif combatMode == COMBAT_MODE_CAMPS  then
		return obj.camps == 0 or obj.camps ~= target.camps
	elseif combatMode == COMBAT_MODE_TEAM then		
    if obj.db.teamUuidLen == 0 or target.db.teamUuidLen == 0 then
        return true
    end  
    for i = 0, obj.db.teamUuidLen - 1 do
      if RoleFFI.ffi_string(obj.db.teamUuid[i].uuid) == target._id then
         return 
      end
    end
		return true	
  elseif combatMode == COMBAT_MODE_FAMILY then	
    if obj.familyUuid == "" or target.familyUuid == "" then	
		    return true
		end
		if obj.familyUuid == target.familyUuid then
		    return
		end
		return true
  elseif combatMode == COMBAT_MODE_WILD then
    if obj.familyUuid ~= "" and target.familyUuid == obj.familyUuid then 
        return --同军团
    end
    if obj.db.teamUuidLen >= 0 and target.db.teamUuidLen >= 0 then
        for i = 0, obj.db.teamUuidLen - 1 do
          if RoleFFI.ffi_string(obj.db.teamUuid[i].uuid) == target._id then
            return --同队
          end
        end
    end
    return true
	end
	return true
end

function human_VS_monster(obj, target)
	-- 根据白名单和怪物阵营设定
	if isInWhiteMonsterList(obj, target) then 
		return 	
	end
	if RoleCombatMode.getCombatMode(obj) == COMBAT_MODE_CAMPS then --阵营模式
	   if obj.camps == 0 or obj.camps ~= target.camps then
	       return true
	   end
	   return
	elseif target.camps == Obj.CAMPS_GOOD then
	   return
	end
	return true
end

-- ***************** 条件作用 ***********************

function dist(data,target,len,maxLen)
	local unit = data.unit
	local target = data.target
	if data.utilityConfig.aoeType == 2 then		--圆
		local targetRadius = Obj.getRadius(target)
		return not Util.roundCollision(unit.tx,unit.ty,len,target.x,target.y,targetRadius) and Util.roundCollision(unit.tx,unit.ty,maxLen,target.x,target.y,targetRadius)
	else
		local v = Util.dist(unit.x,unit.y,target.x,target.y)
		return v>len and v <maxLen
	end
end

function hp(data,obj,value,max)
	local rate = (Obj.getHp(obj)/Obj.getHpMax(obj))*100
	return value<=rate and rate<=max
end

function hpOwner(data,obj,value,max)
	local owner = Obj.getOwner(obj)
	if owner then
		return  hp(data,owner,value,max)
	end
end

function mp(data,obj,value,max)
	local rate = (obj.db.mp /ObjHuman.getMpMax(obj))*100
	return value<=rate and rate<=max
end

function hasBuffCmd(data,obj,cmd,isGood)
	return Buffer.hasCmd(obj,cmd,isGood)
end

function nohasBuffCmd(data,obj,cmd,isGood)
	return not Buffer.hasCmd(obj,cmd,isGood)
end

function hasBuffGroup(data,obj,groupID)
	return Buffer.hasGroup(obj,groupID)
end

-- 判断锁定目标是否有BUFF组
function targetHasBuffGroup(data,obj,groupID)
	return data.target and Buffer.hasGroup(data,data.target,groupID)
end

function nohasBuffGroup(data,obj,groupID)
	return not Buffer.hasGroup(obj,groupID)
end

function hasBufIDCount(data,obj,bufferID,value,max)
	return Buffer.hasBufIDCount(obj,bufferID,value,max)
end

function rand(data,obj,value)
	return random(1,100) <= value*100
end

function targetDist(data,target,value)
	local obj = data.obj
	return Util.dist(obj.x,obj.y,target.x,target.y)<=value
end

function official(data,obj,value,max)
	if not obj.monster_id then
		return
	end
	local t = ExcelMonster.monster[obj.monster_id].monster_type
	return value <= t and t <= max
end

function levelDifference(data,obj,value)
	return  Obj.getLv(data.obj) -  Obj.getLv(data.target)>=value
end

function isMoving(data,obj)
	return obj.path_len and obj.path_len>0
end

function notMonsterType(data,obj,type)
	if obj.obj_type == Obj.TYPE_MONSTER then
		return ExcelMonster.monster[obj.monster_id].monster_type ~= type
	else
		return true
	end
end

function isHide(data,obj,flag)
	return (obj.status == HUMAN_STATUS_HIDE) == (flag==1)
end
